package com.msa.data;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.NoSuchElementException;

/**
 * 循环队列FIFO
 *
 * @author 毕子航 951755883@qq.com
 * @date 2018/12/23
 */
public class MyCycleQueue {
	private int[] data;
	private int size;
	private int head;
	private int tail;

	public MyCycleQueue() {
		this(1 << 3);
	}

	public MyCycleQueue(int size) {
		this.data = new int[size];
		this.size = 0;
		this.head = 0;
		this.tail = -1;
	}

	/**
	 * 从队尾插入，容量不足抛异常
	 *
	 * @param value
	 * @return
	 * @throws IllegalStateException
	 */
	public boolean add(int value) {
		if (full()) {
			throw new IllegalStateException();
		}
		if (tail == data.length - 1) {
			tail = -1;
		}
		data[++tail] = value;
		size++;
		return true;
	}

	public boolean offer(int value) {
		return false;
	}

	/**
	 * 从队头移除，抛出不存在该元素的异常
	 *
	 * @return
	 * @throws NoSuchElementException
	 */
	@NotNull
	public int remove() {
		if (empty()) {
			throw new NoSuchElementException();
		}
		int peek = peek();
		head++;
		size--;
		if (head == data.length) {
			head = 0;
		}
		return peek;
	}

	/**
	 * 取出队列头元素，如果为空返回null
	 *
	 * @return
	 */
	@Nullable
	public int poll() {
		if (empty()) {
			return 0;
		}
		size--;
		return data[head++];
	}

	/**
	 * 类似于{@link #peek() peek},但如果不存在抛异常
	 *
	 * @return
	 * @throws NoSuchElementException
	 */
	@NotNull
	public int element() {
		if (empty()) {
			throw new NoSuchElementException();
		}
		return data[head];
	}

	/**
	 * 查看队列头元素，如果为空返回null
	 *
	 * @return
	 */
	@Nullable
	public int peek() {
		if (empty()) {
			return 0;
		}
		return data[head];
	}

	/**
	 * 队列是否已满
	 *
	 * @return
	 */
	public boolean full() {
		return size == data.length;
	}

	/**
	 * 队列是否为空
	 *
	 * @return
	 */
	public boolean empty() {
		return size == 0;
	}

	/**
	 * 队列的长度
	 *
	 * @return
	 */
	public int size() {
		return size;
	}

	public void display() {
		System.out.print("[");
		for (int i = head; i <= tail; i++) {
			System.out.print(i + "=" + data[i] + " ");
		}
		System.out.print("]");
		System.out.println();
	}
}
